﻿/**
 * File:   battery_widget.c
 * Author: 
 * Brief:  
 *
 * Copyright (c) 2024 - 2024 
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * License file for more details.
 *
 */

/**
 * History:
 * ================================================================
 * 2024-10-15  created
 *
 */


#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/canvas.h"
#include "base/vgcanvas.h"
#include "base/widget_vtable.h"
#include "base/style.h"
#include "tkc/color.h"
#include "tkc/rect.h"
#include "battery_widget.h"


static ret_t battery_widget_get_prop(widget_t* widget, const char* name, value_t* v) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  return_value_if_fail(battery_widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
  if(tk_str_eq(name, WIDGET_PROP_BATTERY_PERCENT)){
      value_set_int(v, battery_widget->battery_percent);
      return RET_OK;
  }
  else if(tk_str_eq(name, WIDGET_PROP_CAP_HEADING_LEFT)){
      value_set_bool(v, battery_widget->cap_heading_left);
      return RET_OK;
  }
  else if(tk_str_eq(name, WIDGET_PROP_IS_CHARGING)){
      value_set_bool(v, battery_widget->is_charging);
      return RET_OK;
  }
  return RET_NOT_FOUND;
}

static ret_t battery_widget_set_prop(widget_t* widget, const char* name, const value_t* v) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
  if(tk_str_eq(name, WIDGET_PROP_BATTERY_PERCENT)){
      battery_widget->battery_percent = value_int(v);
      return RET_OK;
  }
  else if(tk_str_eq(name, WIDGET_PROP_CAP_HEADING_LEFT)){
      battery_widget->cap_heading_left = value_bool(v);
      return RET_OK;
  }
  else if(tk_str_eq(name, WIDGET_PROP_IS_CHARGING)){
      battery_widget->is_charging = value_bool(v);
      return RET_OK;
  }

  return RET_NOT_FOUND;
}

static ret_t battery_widget_on_destroy(widget_t* widget) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  return_value_if_fail(widget != NULL && battery_widget != NULL, RET_BAD_PARAMS);



  return RET_OK;
}

static ret_t battery_widget_paint_shape(widget_t* widget, canvas_t* c){
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  style_t *style = widget->astyle;
  color_t color = style_get_color(style, STYLE_ID_BORDER_COLOR, color_init(0, 255, 0, 255));
  int stroke_width = style_get_int(style, STYLE_ID_BORDER_WIDTH, 3);
  int round = style_get_int(style, STYLE_ID_ROUND_RADIUS, 3);
  
  int cap_width = widget->w / 10, cap_height = widget->h / 2;
  if(battery_widget->cap_heading_left){
    rect_t r_body = rect_init(cap_width, 0, widget->w - cap_width, widget->h);
    rect_t r_cap = rect_init(0, (widget->h - cap_height) / 2, cap_width, cap_height);
    canvas_stroke_rounded_rect(c, &r_body, &r_body, &color, round, stroke_width);
    canvas_set_fill_color(c, color);
    canvas_fill_rect(c, r_cap.x, r_cap.y, r_cap.w, r_cap.h);
  }
  else{
    rect_t r_body = rect_init(0, 0, widget->w - cap_width, widget->h);
    rect_t r_cap = rect_init(widget->w - cap_width, (widget->h - cap_height) / 2, cap_width, cap_height);
    canvas_stroke_rounded_rect(c, &r_body, &r_body, &color, round, stroke_width);
    canvas_set_fill_color(c, color);
    canvas_fill_rect(c, r_cap.x, r_cap.y, r_cap.w, r_cap.h);
  }
  return RET_OK;
}

static ret_t battery_widget_paint_rect(widget_t *widget, canvas_t *c){
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  style_t *style = widget->astyle;
  color_t color = style_get_color(style, STYLE_ID_BG_COLOR, color_init(0, 255, 0, 255));
  int border_width = style_get_int(style, STYLE_ID_BORDER_WIDTH, 3);
  int cap_width = widget->w / 10, cap_height = widget->h / 2;
  if(battery_widget->battery_percent > 20){
    canvas_set_fill_color(c, color);
  }
  else{
    color = color_init(255, 0, 0, 255);
    canvas_set_fill_color(c, color);
  }
  int gap = 1;
  int full_charge_width = widget->w - (border_width + gap) * 2 - cap_width;
  int charged_width = full_charge_width * (battery_widget->battery_percent / 100.0);
  int remain_width = full_charge_width - charged_width;
  if(battery_widget->cap_heading_left){
    canvas_fill_rect(c, border_width + gap + cap_width + remain_width, border_width + gap, charged_width, widget->h - (border_width + gap) * 2);
  }
  else{
    canvas_fill_rect(c, border_width + gap, border_width + gap, charged_width, widget->h - (border_width + gap) * 2);
  }
  return RET_OK;
}

static ret_t draw_lightning(widget_t *widget, canvas_t *c, rect_t r) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  style_t *style = widget->astyle;
  color_t color = style_get_color(style, STYLE_ID_BORDER_COLOR, color_init(255, 0, 0, 255));
  int stroke_width = style_get_int(style, STYLE_ID_BORDER_WIDTH, 3);
  int round = style_get_int(style, STYLE_ID_ROUND_RADIUS, 3);
  // canvas_stroke_rounded_rect(c, &r, &r, &color, round, stroke_width);

  vgcanvas_t* vg = canvas_get_vgcanvas(c); 

  // 保存当前的状态
  vgcanvas_save(vg);
  vgcanvas_begin_path(vg);
  vgcanvas_translate(vg, c->ox + r.x, c->oy + r.y);

  // 绘制闪电图标的路径 
  // assume icon in 6 x 10 size
  vgcanvas_move_to(vg, r.w * (4 / 6.0), r.h * 0); // 起点   
  vgcanvas_line_to(vg, r.w * 0, r.h * (6 / 10.0)); // 向左下
  vgcanvas_line_to(vg, r.w * (2 / 6.0), r.h * (6 / 10.0)); // 向右
  vgcanvas_line_to(vg, r.w * (2 / 6.0), r.h * 1); // 向左下
  vgcanvas_line_to(vg, r.w * 1, r.h * (4 / 10.0)); // 向右上
  vgcanvas_line_to(vg, r.w * (4 / 6.0), r.h * (4 / 10.0)); // 向左
  vgcanvas_close_path(vg); // 关闭路径

  // 设置颜色和线宽
  vgcanvas_set_stroke_color(vg, color);
  vgcanvas_set_fill_color(vg, color);
  vgcanvas_set_line_width(vg, stroke_width);

  // 填充和描边
  vgcanvas_fill(vg);
  vgcanvas_stroke(vg);

  // 恢复之前的状态
  vgcanvas_restore(vg);

  return RET_OK;
}


static ret_t battery_widget_paint_charging_icon(widget_t *widget, canvas_t *c){
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  style_t *style = widget->astyle;

  int cap_width = widget->w / 10, cap_height = widget->h / 2;
  int stroke_width = style_get_int(style, STYLE_ID_BORDER_WIDTH, 3);
  int gap = 1;

  rect_t r;
  int shape_width = widget->w - cap_width - (stroke_width + gap) * 2, shape_heigth = widget->h - (stroke_width + gap) * 2;
  int icon_width = shape_width / 4, icon_height = shape_heigth * 0.9;
  if(battery_widget->cap_heading_left){
    int offset_x = stroke_width + gap + cap_width, offset_y = stroke_width + gap;
    r = rect_init(offset_x + (shape_width - icon_width) / 2, offset_y + (shape_heigth - icon_height) / 2, icon_width, icon_height);
    draw_lightning(widget, c, r);
  }
  else{
    int offset_x = stroke_width + gap, offset_y = stroke_width + gap;
    r = rect_init(offset_x + (shape_width - icon_width) / 2, offset_y + (shape_heigth - icon_height) / 2, icon_width, icon_height);
    draw_lightning(widget, c, r);
  }
  return RET_OK;
}

static ret_t battery_widget_on_paint_self(widget_t* widget, canvas_t* c) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  battery_widget_paint_shape(widget, c);
  battery_widget_paint_rect(widget, c);
  if(battery_widget->is_charging){
    battery_widget_paint_charging_icon(widget, c);
  }
  return RET_OK;
}

static ret_t battery_widget_on_event(widget_t* widget, event_t* e) {
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  return_value_if_fail(widget != NULL && battery_widget != NULL, RET_BAD_PARAMS);

  (void)battery_widget;

  return RET_OK;
}

const char* s_battery_widget_properties[] = {
  NULL
};

TK_DECL_VTABLE(battery_widget) = {.size = sizeof(battery_widget_t),
                          .type = WIDGET_TYPE_BATTERY_WIDGET,
                          .clone_properties = s_battery_widget_properties,
                          .persistent_properties = s_battery_widget_properties,
                          .parent = TK_PARENT_VTABLE(widget),
                          .create = battery_widget_create,
                          .on_paint_self = battery_widget_on_paint_self,
                          .on_paint_border = widget_on_paint_null,
                          .on_paint_background = widget_on_paint_null,
                          .set_prop = battery_widget_set_prop,
                          .get_prop = battery_widget_get_prop,
                          .on_event = battery_widget_on_event,
                          .on_destroy = battery_widget_on_destroy};

widget_t* battery_widget_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
  widget_t* widget = widget_create(parent, TK_REF_VTABLE(battery_widget), x, y, w, h);
  battery_widget_t* battery_widget = BATTERY_WIDGET(widget);
  return_value_if_fail(battery_widget != NULL, NULL);



  return widget;
}

widget_t* battery_widget_cast(widget_t* widget) {
  return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, battery_widget), NULL);

  return widget;
}
